#ifndef OBJECT_H
#define OBJECT_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <surface.h>
#include <coord.h>
#include <color.h>


typedef struct object
{
  /**
   * These defines are meant to easy programming of basic types,
   * but be careful to keep them in sync with object_yable in object.c
   *
   * Newer registed types should use the value returned by
   * add_object_table_entry() function!
   */
#define OBJECT_TYPE_UNDEFINED           0
#define OBJECT_TYPE_LINE                1
  uint8_t type;

  /**
   * draw options, could be OR'ed
   */
#define DRAW_NORMAL          0 /**< nothing special */
#define DRAW_ANTIALIAS       1 /**< use anti-alias drawing */
#define DRAW_FILL            2 /**< if applicable, fill object contents */
  uint8_t draw_opts;

  uint16_t depth;
  color_t color;
  float transp; /**< between 0.0 and 1.0 */
  double kd;       // difuse factor, used for difuse reflexion
  double ks;       // specular factor, used for specular reflexion
  double nphong;   // phong number, used for phongs intensity
} object_t;

#define OBJECT(object) ((object_t*)object)

#define OBJECT_TYPE(object) (OBJECT(object)->type)
#define OBJECT_DRAW_OPTS(object) (OBJECT(object)->draw_opts)
#define OBJECT_DEPTH(object) (OBJECT(object)->depth)
#define OBJECT_COLOR(object) (OBJECT(object)->color)
#define OBJECT_TRANSP( object ) (OBJECT(object)->transp)

#define OBJECT_SET_DRAW_OPT( object, opt ) \
  ( OBJECT_DRAW_OPTS( object ) |= (opt) )

#define OBJECT_UNSET_DRAW_OPT( object, opt ) \
  ( OBJECT_DRAW_OPTS( object ) &= ~(opt) )


object_t *
object_new( uint16_t type );

void
__object_free( object_t *object );
#define object_free( object ) \
  __object_free( OBJECT(object) )


void
__object_init( object_t *object, color_t color, float transp, uint16_t depth,
	     uint8_t draw_opts );

#define object_init( object, color, transp, depth, draw_opts ) \
  __object_init( OBJECT(object), (color), (transp), (depth), (draw_opts) )

#define object_init5( object, color, transp, depth, draw_opts ) \
  object_init( (object), (color), (transp), (depth), (draw_opts) )

#define object_init4( object, color, transp, depth ) \
  object_init( (object), (color), (transp), (depth), DRAW_NORMAL )

#define object_init3( object, color, transp ) \
  object_init( (object), (color), (transp), 0, DRAW_NORMAL )

#define object_init2( object, color ) \
  object_init( (object), (color), 0.0, 0, DRAW_NORMAL )


char *
__object_str( object_t *object );
#define object_str( object ) \
  __object_str( OBJECT(object) )


void
__object_draw( object_t *object, surface_t *surface );
#define object_draw( object, surface ) \
  __object_draw( OBJECT(object), (surface) )


#endif /* OBJECT_H */
